#include "HTTP.h"
#include "../Stringops/StringOps.h"
#include "../Errors/errors.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <algorithm>

void HTTPRequest::fill(std::string url) {
	// Split URL into parts
	struct URL parts = generate_url(url);

	// Resolve host name
	struct addrinfo hints, *res;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags |= AI_CANONNAME;
	int result = getaddrinfo(parts.host_name.c_str(), NULL, &hints, &res);
	// Do error checking
	if(result < 0) {
		auto_set_error("HTTP Request");
		printf("%s\n", get_error());
		return;
	}

	freeaddrinfo(res);

	// Get address information
	struct sockaddr_in host;
	host.sin_family = AF_INET;
	host.sin_port = htons(80);
	memcpy(&host.sin_addr.s_addr, res->ai_addr->sa_data+2, 4);

	// Connect to host
	int sock = socket(AF_INET, SOCK_STREAM, 0);
	result = connect(sock, (struct sockaddr*)&host, sizeof(host));
	// do error checking
	if(result < 0) {
		auto_set_error("HTTP Request");
		printf("%s\n", get_error());
		return;
	}

	// Send HTTP request
	//printf("Before send\n");
	std::string request = "GET " + parts.path + " HTTP/1.0";
	request.push_back(13);
	request.push_back(10);
	request = request + "Host: " + parts.host_name;
	request.push_back(13);
	request.push_back(10);
	request.push_back(13);
	request.push_back(10);
	printf("Request: %s\n",request.c_str());
	result = send(sock, request.c_str(), request.size(), 0);
	// do error checking
	if(result < 0) {
		auto_set_error("HTTP Request");
		printf("%s\n", get_error());
		return;
	}

	// Get response
	std::string response;
	char c;

	int _res;
	while((_res = recv(sock, &c, 1, 0)) == 1)
                response.push_back(c);
	// do error checking
	if(result < 0) {
		auto_set_error("HTTP Request");
		printf("%s\n", get_error());
		return;
	}

	// Parse response
	std::remove(response.begin(), response.end(), '\r');

	error_code = get_error_code(response);
	//printf("1\n");
	error_description = get_error_description(response);
	//printf("2\n");
	date = get_date(response);
	//printf("3\n");
	expires = get_expires(response);
	//printf("4\n");
	body = get_body(response);
	//printf("5\n");
	url_identitiy = url;
	//printf("Code: %d. Body: %s.\n", error_code, body.c_str());
}

std::vector<char> HTTPRequest::to_array() {
	//unsigned int error_des_len  = error_description.size();
	//unsigned int date_len  = date.size();
	//unsigned int expires_len  = expires.size();
	//unsigned int body_len  = body.size();
	//vector<char> pkt(error_des_len + date_len+expires_len+body_len);
	std::vector<char> pkt;
	/*for(unsigned int i = 0; i < error_description.size(); i++)
		pkt.push_back(error_description[i]);
	for(unsigned int j = 0; j < date.size(); j++)
		pkt.push_back(date[j]);
	for(unsigned int k = 0; k < expires.size(); k++)
		pkt.push_back(expires[k]);*/
	for(unsigned int l = 0; l < body.size(); l++)
		pkt.push_back(body[l]);
	pkt.push_back(0);
	//memcpy(pkt.data(), &error_description, error_des_len);
	//memcpy(pkt.data()+error_des_len, &date, date_len);
	//memcpy(pkt.data()+error_des_len+date_len, &expires, expires_len);
	//memcpy(pkt.data()+error_des_len+date_len+expires_len, &body, body_len);
	return pkt;
}
